#include "projection_screen.h"
#include "tx_flash.h"
#include "RF433.h"

u8 PS_sta = 0;
u8 PS_sta_new = 0;
u8 PS_dir = 0;
u8 PS_err = 0;
u16 PS_pwm = 0;
u16 PS_current = 0;
u16 cnt_OV = 0;

u8 cnt_rf_timeout = 0;

u8 cnt_reset = 0;

u16 cnt_stall = 0;

PS_def_position PS_postion = {0};
PS_def_position PS_tar_postion = {0};

_lv_filter PS_angle = {0};
_lv_filter PS_cur = {0};

void P_screen_init(void)
{
    PS_sta = PS_STANDBY;
    PS_sta_new = PS_STANDBY;

    PS_angle.coe = 2;

    //读flash 获取位置
    flash_read(FLASH_POS_ADDR, (u8*)(&PS_postion), sizeof(PS_postion));
    if(PS_postion.circle>32768 || PS_postion.circle<100){
        //越界复位
        PS_postion.angle = 0;
        PS_postion.circle = 1000;
        flash_erase_sector(FLASH_POS_ADDR);
        flash_program(FLASH_POS_ADDR, (u8*)(&PS_postion), sizeof(PS_postion));
    }

    PS_dir = e_PS_open;
} 

/*
    正传，反转，停止，归零，到尾
*/
void P_screen_crt_loop(void)
{
    switch (PS_sta){
        case PS_STANDBY:
            PS_SET_OPEN_PWM(0);
            PS_SET_CLOSE_PWM(0);
            // P15 ^= 1;
            break;

        case PS_RUN:
            if(PS_pwm<RUNNING_PWM){
                PS_pwm+=10;
            }else{
                PS_pwm = RUNNING_PWM;
            }

            if(PS_dir==e_PS_open){
                // P07 ^= 1; 
                PS_SET_OPEN_PWM(PS_pwm);
                if(PS_postion.circle>=PS_tar_postion.circle){
                    PS_sta_new = PS_STOP;
                }
            }else{
                // P06 ^= 1;
                PS_SET_CLOSE_PWM(PS_pwm);
                if(PS_postion.circle<=PS_tar_postion.circle){
                    PS_sta_new = PS_STOP;
                }
            }
            if(PS_current>CUR_OVERLOAD){
                if(cnt_OV++>5){
                    cnt_OV = 0;
                    PS_sta_new = PS_ERR;
                    PS_err = ERR_OVERCUR;
                    P_screen_set_err();
                }
            }else{
                cnt_OV = 0;
            }
            break;

        case PS_STOP:
            if(PS_pwm>0){
                PS_pwm-=10;
            }else{
                PS_pwm = 0;
            }

            if(PS_dir==e_PS_open){
                PS_SET_OPEN_PWM(PS_pwm);
            }else{
                PS_SET_CLOSE_PWM(PS_pwm);
            }
            
            if(PS_pwm==0){
                PS_sta_new = PS_STANDBY;
                // flash_erase_sector(FLASH_POS_ADDR);
                // flash_program(FLASH_POS_ADDR, (u8*)(&PS_postion), sizeof(PS_postion));
            }
            break;

        case PS_RESET:
            if(PS_pwm<RESET_PWM){
                PS_pwm += 10;
                if(PS_pwm>RESET_PWM){
                    PS_pwm = RESET_PWM;
                }   
            }
            PS_SET_CLOSE_PWM(PS_pwm);
            break;

        case PS_ERR:
            PS_SET_OPEN_PWM(0);
            PS_SET_CLOSE_PWM(0);
            break;

        default:
            break;
    }
}

/*
    init,standby,running(up,down),reset,err(overcurrent.onangle,overvolt,lowvolt,stalling)
*/
void P_screen_sta_loop(void)
{
    if(PS_sta == PS_sta_new){
        return;
    }

    PS_sta = PS_sta_new;

    switch (PS_sta){
        case PS_STANDBY:

            break;

        case PS_RUN:

            break;

        case PS_STOP:

            break;

        case PS_RESET:
            PS_postion.angle = 0;
            PS_postion.circle = PS_ZERO_CIRCLE;
            break;

        case PS_ERR:

            break;

        default:
            break;
    }
}

/*
    reset|
         |-reset start
         |-reset running
         |-reset stop
         |-reset turn back
         |-reset done

    暂时先递增到复位速度回调
    需要长按按键，松开就停止，记录当前为起始位置

*/
void P_screen_reset_loop(void)
{

}

void P_screen_set_move(u8 dir, u16 target)
{
    if(PS_sta==PS_ERR){
        return;
    }
    PS_dir = dir;
    // PS_tar_postion.angle = target;
    PS_tar_postion.circle = target;
    PS_sta_new = PS_RUN;
}

void P_screen_set_stop(void)
{
    if(PS_sta==PS_ERR){
        return;
    }
    PS_sta_new = PS_STOP;
}

void P_screen_set_reset(void)
{
    PS_pwm = 0;
    PS_SET_OPEN_PWM(0);
    PS_SET_CLOSE_PWM(0);
    PS_sta_new = PS_RESET;
}

void P_screen_set_err(void)
{
    //错误后需要断电重启
    PS_pwm = 0;
    PS_SET_OPEN_PWM(0);
    PS_SET_CLOSE_PWM(0);
}

/*
    传入adc采样值
        |-滤波
        |-确定当前值
        |-判断方向
        |-判断圈数（4096过零点）

    背面朝自己，尖头向上 顺时针方向圈数增加
    顺时针转，电阻变大电压变大 最大-不是10k
    逆时针转，电阻变小电压变小 最小-不是0k
*/
#define ANGLE_ADC_CRO   4000
#define ANGLE_ADC_MAX   3720    //需要手动测量实际值
#define ANGLE_ADC_MIN   550
#define ANGLE_ADC_DIFF  150
#define STALL_MAX       2000

void P_sceen_angle_convert(u16 value)
{
    bit data_valid = 0;//有效数据==0，进入过零==1
    static bit b_set = 0;
    static u16 ls_value = 0;
    static u8 cnt_cross = 100;

    if(PS_sta != PS_RUN){
        return;
    }

    data_valid = 0;

    if(cnt_stall++>STALL_MAX){
        cnt_stall = 0;
        PS_sta_new = PS_ERR;
        PS_err = ERR_STALL;
        P_screen_set_err();
        return;
    }

    if(value>=ANGLE_ADC_CRO){
        //一圈
        data_valid = 1;

        if(b_set==0){
            if(cnt_cross++>103){
                cnt_cross = 100;
                b_set = 1;
                cnt_reset = 0;
                cnt_stall = 0;
                if(PS_dir==e_PS_open){
                    PS_postion.circle++;//顺时针圈数增多
                    //adc值变小
                    PS_angle.sum = (u32)ANGLE_ADC_MAX<<PS_angle.coe;
                    PS_angle.output = ANGLE_ADC_MAX;
                }else{
                    PS_postion.circle--;//逆时针圈数减小
                    PS_angle.sum = (u32)ANGLE_ADC_MIN<<PS_angle.coe;
                    PS_angle.output = ANGLE_ADC_MIN;
                }
            }
        }
    }else{
        if(b_set==1){
            data_valid = 1;
            if(cnt_cross--<97){
                cnt_cross = 100;
                b_set = 0;
            }
        }else{
            if(PS_dir==e_PS_open){
                //adc减小
                if(value>ls_value+ANGLE_ADC_DIFF){
                    data_valid = 1;
                }
            }else{
                if(value+ANGLE_ADC_DIFF<ls_value){
                    data_valid = 1;
                }
            }
        }
 
        ls_value = value;
    }

    if(data_valid==0){
        //数据有效
        //滤波
        PS_angle.sum = PS_angle.sum + value - PS_angle.output;
        PS_angle.output = PS_angle.sum >> PS_angle.coe;
    }

    //更新角度  注意外力使用时更新角度
    PS_postion.angle = PS_angle.output;
}

void P_screen_current_convert(u16 value)
{
    //滤波
    PS_cur.sum = PS_cur.sum + value - PS_cur.output;
    PS_cur.output = PS_cur.sum >> PS_cur.coe;

    PS_current = PS_cur.output;

    // if(PS_current>STOP_END_CUR){
    //     PS_SET_OPEN_PWM(0);
    //     PS_SET_CLOSE_PWM(0); 
    //     PS_sta_new = PS_ERR;
    //     PS_err = ERR_OVERCUR;
    // }
}

void P_screen_RF433_loop(void)
{
    if(cnt_rf_timeout<250){
        cnt_rf_timeout++;
    }

    if(PS_sta==PS_RESET){
        if(cnt_rf_timeout>30){
            //reset 按键释放
            P_screen_set_stop();
        }
    }

    if(b_e){
        b_e = 0;

        if(rf_value==RF_CMD_RESET){
            if(PS_sta!=PS_RESET){
                if(cnt_reset++>10){
                    cnt_reset = 0;
                    P_screen_set_reset();
                }
            }
        }else{
            cnt_reset = 0;
        }
    
        if(rf_value == rf_value_ls){
            if(cnt_rf_timeout<30){
                //连续码
                cnt_rf_timeout = 0;
                return;
            }
        }else{
            rf_value_ls = rf_value;
        }
        cnt_rf_timeout = 0;

        if(PS_sta==PS_ERR){
            return;
        }

        switch (rf_value){
            case RF_CMD_OPEN:
                if(PS_sta==PS_RUN){
                    if(PS_dir==e_PS_close){
                        P_screen_set_stop();
                    }
                }else{
                    if(PS_sta!=PS_RESET){
                        P_screen_set_move(e_PS_open, PS_END_STOP);
                    }else{
                        P_screen_set_stop();
                    }
                }
                
                break;

            case RF_CMD_CLOSE:
                if(PS_sta==PS_RUN){
                    if(PS_dir==e_PS_open){
                        P_screen_set_stop();
                    }
                }else{
                    if(PS_sta!=PS_RESET){
                        // P_screen_set_move(e_PS_close, PS_START_STOP);
                        P_screen_set_move(e_PS_close, PS_START_STOP-100);//debug
                    }else{
                        P_screen_set_stop();
                    }
                }
                break;

            case RF_CMD_STOP:
                P_screen_set_stop();
                break;

            // case RF_CMD_RESET:

            //     break;

            default:break;
        }
    }
}